package com.geovis.emergency.spd.biz.pc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.geovis.common.auth.util.AuthUtil;
import com.geovis.common.core.constant.CommonConstants;
import com.geovis.common.mybatis.page.PageParam;
import com.geovis.common.mybatis.page.PageResult;
import com.geovis.common.socketio.dto.SocketIoMessage;
import com.geovis.common.socketio.service.ISocketIoService;
import com.geovis.emergency.spd.biz.agora.AgoraTokenDTO;
import com.geovis.emergency.spd.biz.agora.AgoraTokenUtil;
import com.geovis.emergency.spd.biz.pc.mapper.PcDiscussMapper;
import com.geovis.emergency.spd.biz.pc.service.IPcDiscussService;
import com.geovis.emergency.spd.biz.pc.service.IPcDiscussStaffService;
import com.geovis.emergency.spd.biz.system.service.ISystemUserService;
import com.geovis.emergency.spd.entity.pc.entity.PcDiscuss;
import com.geovis.emergency.spd.entity.pc.entity.PcDiscussStaff;
import com.geovis.emergency.spd.entity.pc.pojo.constant.PcDiscussConstant;
import com.geovis.emergency.spd.entity.pc.pojo.constant.PcMessageConstant;
import com.geovis.emergency.spd.entity.pc.pojo.dto.PcDiscussDTO;
import com.geovis.emergency.spd.entity.pc.pojo.dto.PcDiscussQueryDTO;
import com.geovis.emergency.spd.entity.pc.pojo.dto.PcDiscussSaveDTO;
import com.geovis.emergency.spd.entity.system.entity.SystemUser;
import com.geovis.emergency.spd.util.MsgUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 应急预案指挥模块-研判会商 服务实现类
 * </p>
 *
 * @author 曾德实
 * @since 2022-05-01
 */

@Service
@RequiredArgsConstructor
@Slf4j
public class PcDiscussServiceImpl extends ServiceImpl<PcDiscussMapper, PcDiscuss> implements IPcDiscussService {

    private final IPcDiscussStaffService pcDiscussStaffService;

    private final AgoraTokenUtil agoraTokenUtil;

    private final ISocketIoService socketIoService;

    private final ISystemUserService systemUserService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void save(PcDiscussSaveDTO saveDTO) {

        // 1、获取所有的用户
        List<SystemUser> systemUserList = systemUserService.list(Wrappers.lambdaQuery(SystemUser.class).in(SystemUser::getId,saveDTO.getStaffIdList()));
        Map<String, SystemUser> systemUserMap = IterUtil.toMap(systemUserList, SystemUser::getId);

        // 2、保存会议
        PcDiscuss pcDiscuss = BeanUtil.copyProperties(saveDTO, PcDiscuss.class);
        pcDiscuss.setStartTime(LocalDateTime.now()).setStatus(PcDiscussConstant.STATUS_DOING).setCreatorId(AuthUtil.getCurrentUserId());
        save(pcDiscuss);

        // 3、添加当前人入会议，构建参与会议人员信息，并入库
        saveDTO.getStaffIdList().add(AuthUtil.getCurrentUserId());
        List<PcDiscussStaff> staffList = saveDTO.getStaffIdList().stream().map(personId -> {

            PcDiscussStaff staff=  new PcDiscussStaff().setPcDrillId(pcDiscuss.getPcDrillId())
                    .setPcDiscussId(pcDiscuss.getId()).setStatus(CommonConstants.NO)
                    .setPersonId(personId);
            if(null!=systemUserMap.get(personId))
            {
                staff.setPersonName(systemUserMap.get(personId).getRealName());
            }
            return staff;
        }).collect(Collectors.toList());
        pcDiscussStaffService.saveBatch(staffList);

        // 4、发送消息
        Map<String, String> socketMap = MapUtil.newHashMap();
        socketMap.put("pcDiscussId", pcDiscuss.getId());
        socketMap.put("personName", AuthUtil.getCurrUser().getRealName());
//        socketIoService.sendMessage(SocketIoMessage.builder().
//                toUserIdSet(saveDTO.getStaffIdList()).eventName(PcMessageConstant.TYPE_DISCUSS_INVITATION).data(socketMap).build());
        saveDTO.getStaffIdList().stream().forEach(userId->{
            MsgUtil.pushMsgByUser(PcMessageConstant.TYPE_DISCUSS_INVITATION,saveDTO.getTitle(),saveDTO.getContent(),saveDTO.getPcDrillId(),pcDiscuss.getId(),userId);
        });


    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public AgoraTokenDTO join(String pcDiscussId) {
        PcDiscuss pcDiscuss = getById(pcDiscussId);
        Assert.notNull(pcDiscuss, "该会议不存在!");
        Assert.isTrue(StrUtil.equals(pcDiscuss.getStatus(), PcDiscussConstant.STATUS_DOING), "该会议不是正在进行中的会议!");

        String currentUserId = AuthUtil.getCurrentUserId();
        PcDiscussStaff pcDiscussStaff = pcDiscussStaffService.getOne(Wrappers.lambdaQuery(PcDiscussStaff.class).eq(PcDiscussStaff::getPcDiscussId, pcDiscussId)
                .eq(PcDiscussStaff::getPersonId, currentUserId));
        Assert.notNull(pcDiscussStaff, "不好意思，您不在此次会议当中!");

        AgoraTokenDTO result = agoraTokenUtil.getToken(pcDiscussId);
        pcDiscussStaff.setStatus(CommonConstants.YES).setJoinTime(LocalDateTime.now()).setUid(result.getUid());
        pcDiscussStaffService.updateById(pcDiscussStaff);

        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void finish(String pcDiscussId) {
        String currentUserId = AuthUtil.getCurrentUserId();
        PcDiscuss pcDiscuss = getById(pcDiscussId);
        Assert.notNull(pcDiscuss, "该会议不存在!");
        Assert.isTrue(StrUtil.equals(pcDiscuss.getCreatorId(), currentUserId), "您没有权限结束会议!");
        pcDiscuss.setStatus(PcDiscussConstant.STATUS_FINISH).setEndTime(LocalDateTime.now());
        updateById(pcDiscuss);

        // 发送消息
        List<PcDiscussStaff> pcDiscussStaffList = pcDiscussStaffService.list(Wrappers.lambdaQuery(PcDiscussStaff.class).eq(PcDiscussStaff::getPcDiscussId, pcDiscussId));
        socketIoService.sendMessage(SocketIoMessage.builder().
                toUserIdSet(pcDiscussStaffList.stream().map(PcDiscussStaff::getPersonId).collect(Collectors.toSet()))
                .eventName(PcMessageConstant.TYPE_DISCUSS_CREATE).data(pcDiscuss.getId()).build());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void leave(String pcDiscussId) {
        String currentUserId = AuthUtil.getCurrentUserId();
        PcDiscussStaff pcDiscussStaff = pcDiscussStaffService.getOne(Wrappers.lambdaQuery(PcDiscussStaff.class).eq(PcDiscussStaff::getPcDiscussId, pcDiscussId)
                .eq(PcDiscussStaff::getPersonId, currentUserId));
        Assert.notNull(pcDiscussStaff, "不好意思，您不在此会议当中!");
        pcDiscussStaff.setLeaveTime(LocalDateTime.now());
        pcDiscussStaffService.updateById(pcDiscussStaff);
    }

    @Override
    public List<PcDiscussDTO> list(PcDiscussQueryDTO queryDTO) {
        return baseMapper.selectByList(buildWrapper(queryDTO));
    }

    @Override
    public PageResult<PcDiscussDTO> listPage(PageParam<PcDiscussQueryDTO> pageParam) {
        PcDiscussQueryDTO queryDTO = pageParam.getQuery();
        IPage<PcDiscussDTO> page = pageParam.buildPage();
        QueryWrapper<Object> wrapper = buildWrapper(queryDTO);
        baseMapper.selectByPage(page, wrapper);
        return new PageResult<>(page);
    }

    /**
     * 构建 wrapper
     *
     * @param queryDTO
     * @return
     */
    private QueryWrapper<Object> buildWrapper(PcDiscussQueryDTO queryDTO) {
        QueryWrapper<Object> wrapper = Wrappers.query();
        if (ObjectUtil.isEmpty(queryDTO)) {
            return wrapper;
        }
        wrapper.eq(ObjectUtil.isNotEmpty(queryDTO.getStatus()), "a.status", queryDTO.getStatus());
        wrapper.eq(ObjectUtil.isNotEmpty(queryDTO.getPcDrillId()), "a.pc_drill_id", queryDTO.getPcDrillId());
        return wrapper;
    }


}
